import numpy as np


# 1.数组：存放相同类型元素集合 array numpy.array(object)
def test01():
    a = np.array([1, 3, 5, 7, 9])  # 整数
    print(a, a.dtype)
    # np.arange(start,stop,step,dtype)函数创建数值范围返回数组对象(左闭右开)
    b = np.arange(0, 10, 2)  # 初试、结束、步长
    print(b)
    c = np.arange(1, 10, 2, dtype=np.float64)
    print(c)
    d = np.arange(1, -10, -3)  # 递减
    print(d)
    # linspace(start,stop,num,endpoint,retstep,dtype)函数创建等差数组
    e = np.linspace(0, 10, 9)
    print(e)
    f = np.linspace(0, 10, 10, endpoint=False)
    print(f)
    g = np.linspace(0, 10, 10, endpoint=False,
                    retstep=True)  # 初始、结束、个数、是否包含结尾、返回数组和公差
    print(g, g[0], g[1])
    # logspace(start,stop,num,endpoint,base,dtype)创建等比数组（base是底数）
    h = np.logspace(0, 3, 4)
    print(h)
    i = np.logspace(0, 3, 4, base=2)  # base**start base**end 个数 底数
    print(i)


# 二维数组
def test02():
    a = np.array([[1, 3, 5], [2, 4, 6]])  # list包括list 或者元组
    print(a)
    # 转置 行为0轴，列为纵轴
    b = a.T
    print(b)
    # ones(shape,dtype)生成全为1的数组  形状 和 类型
    c = np.ones([2, 3], dtype=np.int32)
    print(c)
    # zeros(shape,dtype)生成全为0的数组
    d = np.zeros([3, 4])
    print(d)
    # full(shape,fill_value,dtype)指定数据填充生成数组
    e = np.full([2, 3], 10)
    print(e)
    # identity(n,dtype)创建单位矩阵
    f = np.identity(3, dtype=np.int32)
    print(f)


# 索引访问：一维:ndarray[index] 二维：ndarray[所在0轴索引][所在1轴索引]/[所在0轴索引,所在1轴索引]
def test03():
    a = np.array([1, 3, 5, 7, 9])  # 一维
    print(a[4], a[-4])
    b = np.array([[1, 3, 5, 7], [2, 4, 6, 8], [7, 8, 9, 10]])  # 二维
    print(b[2][3], b[1, 2], b[-1][-2])
    # 切片访问 (左闭右开)
    print(a[1:3], "  ", a[:3], "  ", a[1:])
    print(a[1:-1:2])
    c = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(c[1:2, 1:2])  # 切出的依旧是二维数组(当0轴1轴都是切片),若单个切片单个标量切出的是一位数组
    print(c[:2, 1:])
    print(c[1:2, 1])
    # 布尔索引
    a1 = np.array([1, 2, 3, 4])
    b1 = np.array([True, False, True, False])  # 布尔索引数组必须与原数组形状一致
    print(a1[b1])  # True留下 False删除 (与)
    b2 = np.array([[True, False, True], [True, False, True],
                   [True, False, True]])
    print(c[b2])  # 返回的一定是一维数组
    # 深浅访问
    a3 = np.array([1, 2, 3])
    b3 = np.array([False, True, True])
    e = a3[b3]
    print(e)  # 此时对e数组的改动并不会改变原数组a3的大小
    a4 = np.array([7, 8, 9])
    f = a4[1:]
    f[1] = 100
    print(f)
    print(a4)  # 切片访问时浅层复制，影响原值
    # 花式索引（与索引数组形状相同，属于深层复制）
    d = [1, 2, 3]
    print(a[d])  # 把d作为数组a的索引(逐个索引)
    g = np.array([[1, 2], [3, 4]])
    print(a[g])  # 返回二维数组(同g相同的形状)
    m = [1, 2]
    n = [0, 1]
    print(c[m, n])  # 与花值索引相同形状，即返回一位数组
    M = np.array([[1, 1], [2, 0]])
    N = np.array([[1, 0], [2, 2]])
    print(c[M, N])  # 返回的是二维数组


# 数据处理
def test04():
    # 连接数组 concatenate((a1,a2,...),axis)函数 沿指定轴连接多个数组
    # a1 a2 ... 指的是要连接的数组 除了指定的轴，其他轴元素个数必须相同
    a = np.array([[1, 2], [3, 4]])
    b = np.array([[5, 6]])
    ab = np.concatenate((a, b))
    print(ab)
    # vstack((a1,a2)) 垂直堆叠多个数组
    vab = np.vstack((a, b))
    print(vab)
    # hstack((a1,a2)) 水平堆叠多个数组
    hab = np.hstack((a, b.T))
    print(hab)

    # 分割数组 split(ary,index_or_sections,axis) index_or_sections是整数或数组，是整数就用该
    # 平均分配，如果是数组，则为延着指定轴的切片操作
    # vsplit(ary,index_or_sections) 垂直方向分割数组
    # hsplit(ary,index_or_sections)水平方向分割数组
    a1 = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
    b1 = np.split(a1, 3)
    print(b1)
    a1 = np.arange(9)
    sections = np.array([4, 7])
    b1 = np.split(a1, sections)
    print(b1)
    a2 = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12],
                   [13, 14, 15, 16]])
    b2 = np.split(a2, 4)
    print(b2)
    sections = np.array([1, 2])
    b2 = np.split(a2, sections)
    print(b2)
    # 数组可以进行py的算数运算
    # 数组广播：先比较形状再比较维度最后才是轴长，如果维度不相等，才会在维度较低的数组旁边填充1
    #   维度相同，要么对应轴长相同，要么其中一个轴长度为1，轴为1的会被扩展
    a = np.array([1, 3, 5])
    print(a + 2)
    a1 = np.array([1, 2])
    b1 = np.array([[3, 4], [5, 6]])
    print(a1 + b1)
    a2 = np.array([[1, 2]])
    b2 = np.array([[3], [4]])
    print(a2 + b2)


# 常用统计函数
def test05():
    # rand(d0,d1,...) 0-1 左闭右开随机浮点
    a1 = np.random.rand(10)
    print(a1)
    a1 = np.random.rand(3, 4)
    print(a1)
    # randint(low,high,size,dtype) 返回随机整数
    a2 = np.random.randint(3, 7, (5, ))
    print(a2)
    a2 = np.random.randint(3, 7, (3, 4))
    print(a2)
    # normal(loc,scale,size) 正态分布随机数,loc表示平均值,scale表示标准差,
    a3 = np.random.normal(10, 3, (3, 4))
    print(a3)
    # randn(d0,d1,...) 标准正态分布
    a3 = np.random.randn(3, 4)
    print(a3)
    # sort(a,axis=-1,kind='quicksort',order=None) 按轴对数组排序函数
    a4 = np.random.randint(0, 10, (3, 4))
    print(a4)
    b4 = np.sort(a4, axis=0)
    print(b4)
    # argsort(a,axis=-1,kind='quicksort',order=None)对数组进行排序索引，即轴排序索引
    b4 = np.argsort(a4)
    print(b4)
    # 聚合函数
    # 求和 sum(a,axis=None)
    # nansum() 忽略NaN值
    # 使用numpy.ndarry.sum(axis=None)方法
    a5 = np.array([[1, 2], [3, 4]])
    print(np.sum(a5))
    print(a5.sum(axis=1))

    # 求最大值 amax(a,axis=Nome)
    # nanmax()函数 忽略NaN值
    # 使用numpy.ndarry.max(axis=None)方法
    print(np.amax(a5))
    print(a5.max(axis=1))
    # 求最小值 amin(a,axis=Nome)
    # nanmin()函数 忽略NaN值
    # 使用numpy.ndarry.min(axis=None)方法
    print(np.amin(a5))
    print(a5.min(axis=1))
    # 求最大值 mean(a,axis=Nome)
    # nanmean()函数 忽略NaN值
    # 使用numpy.ndarry.mean(axis=None)方法
    print(np.mean(a5))
    print(a5.mean(axis=1))
    # 求加权平均值 average(a,axis=None,weight=None)
    print(np.average(a5, weights=[[0.7, 0.1], [0.1, 0.1]]))  # 权和为1


# 数组的保存与读取
def test06():
    # save(file,arr,allow_pickle=True,fix_imports=True) - .npy只能保存一个数组
    a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    np.save("E:\\array_save", a)
    # savez(file) 多个数组保存到未压缩的 - .npz文件中
    b = np.array([1, 2, 3, 4, 5, 6, 7])
    np.savez("E:\\array_savez", array_a=a, array_b=b)
    # savez_compressed(file)函数 多个数组保存到压缩的.npz二进制文件中
    np.savez_compressed("E:\\array_savezc", array_a=a, array_b=b)

    # 读取文件中的数组 load(file,mmap_mode,allow_pickle,fix_imports)
    a2 = np.load("E:\\array_save.npy")
    print(a2)
    arr = np.load("E:\\array_savez.npz")
    print(arr['array_a'])
    print(arr['array_b'])
    arr = np.load("E:\\array_savezc.npz")
    print(arr['array_a'])
    print(arr['array_b'])


if __name__ == "__main__":
    # test01()
    # test02()
    # test03()
    test04()
    # test05()
    # test06()
